package dao

import (
	"ai_srv/basic/config"
	"ai_srv/handler/models"
	"context"
	"fmt"
	"strings"
	"time"
)

// SimpleWeatherData 简单天气数据结构
// 用于存储和传递天气信息，支持多轮对话中的天气查询功能
// 包含基本的天气要素，满足用户日常天气查询需求
type SimpleWeatherData struct {
	City        string  `json:"city"`        // 城市名称，支持中文城市名
	Temperature float64 `json:"temperature"` // 温度，单位：摄氏度
	Description string  `json:"description"` // 天气描述，如"晴天"、"多云"、"小雨"等
	Humidity    int     `json:"humidity"`    // 湿度，单位：百分比
	WindSpeed   float64 `json:"wind_speed"`  // 风速，单位：公里/小时
}

// 城市坐标映射表
// 包含主要城市的经纬度坐标，用于天气查询
// 支持全国主要城市，覆盖一线、二线城市和重要地级市
// 坐标数据基于WGS84坐标系，确保定位准确性
var cityCoordinates = map[string]struct {
	Lat  float64 // 纬度
	Lon  float64 // 经度
	Name string  // 城市名称
}{
	"上海":   {31.2304, 121.4737, "上海"},
	"北京":   {39.9042, 116.4074, "北京"},
	"广州":   {23.1291, 113.2644, "广州"},
	"深圳":   {22.5431, 114.0579, "深圳"},
	"杭州":   {30.2741, 120.1551, "杭州"},
	"南京":   {32.0603, 118.7969, "南京"},
	"苏州":   {31.2989, 120.5853, "苏州"},
	"成都":   {30.5728, 104.0668, "成都"},
	"重庆":   {29.4316, 106.9123, "重庆"},
	"武汉":   {30.5928, 114.3055, "武汉"},
	"西安":   {34.3416, 108.9398, "西安"},
	"天津":   {39.3434, 117.3616, "天津"},
	"青岛":   {36.0986, 120.3719, "青岛"},
	"大连":   {38.9140, 121.6147, "大连"},
	"厦门":   {24.4798, 118.0819, "厦门"},
	"宁波":   {29.8683, 121.5440, "宁波"},
	"福州":   {26.0745, 119.2965, "福州"},
	"长沙":   {28.2278, 112.9388, "长沙"},
	"郑州":   {34.7466, 113.6254, "郑州"},
	"济南":   {36.6512, 117.1201, "济南"},
	"沈阳":   {41.8057, 123.4315, "沈阳"},
	"哈尔滨":  {45.7732, 126.6577, "哈尔滨"},
	"长春":   {43.8171, 125.3235, "长春"},
	"石家庄":  {38.0428, 114.5149, "石家庄"},
	"太原":   {37.8706, 112.5489, "太原"},
	"呼和浩特": {40.8414, 111.7519, "呼和浩特"},
	"兰州":   {36.0611, 103.8343, "兰州"},
	"西宁":   {36.6232, 101.7782, "西宁"},
	"银川":   {38.4872, 106.2309, "银川"},
	"乌鲁木齐": {43.8256, 87.6168, "乌鲁木齐"},
	"拉萨":   {29.6520, 91.1721, "拉萨"},
	"昆明":   {25.0389, 102.7183, "昆明"},
	"贵阳":   {26.6470, 106.6302, "贵阳"},
	"南宁":   {22.8170, 108.3669, "南宁"},
	"海口":   {20.0444, 110.1999, "海口"},
	"三亚":   {18.2479, 109.5027, "三亚"},
	"合肥":   {31.8206, 117.2272, "合肥"},
	"南昌":   {28.6820, 115.8579, "南昌"},
}

// GetSimpleWeatherInfo 获取简单天气信息
//
// 功能特性：
// - 智能城市识别：支持中文城市名称查询
// - 模拟数据支持：提供稳定的天气数据，确保功能可用性
// - 容错处理：未找到城市时自动使用默认城市
// - 多轮对话集成：与AI对话系统无缝集成
//
// 参数:
//   - ctx: 上下文，用于请求超时控制
//   - city: 城市名称，支持中文城市名
//
// 返回:
//   - *SimpleWeatherData: 天气信息结构体
//   - error: 错误信息
func GetSimpleWeatherInfo(ctx context.Context, city string) (*SimpleWeatherData, error) {
	// 输入验证：确保城市名称不为空
	if city == "" {
		return nil, fmt.Errorf("城市名称不能为空")
	}

	// 查找城市坐标：支持精确的城市名称匹配
	coords, exists := cityCoordinates[city]
	if !exists {
		// 容错处理：如果没找到指定城市，使用默认城市（上海）
		// 这确保了天气查询功能的稳定性
		coords = cityCoordinates["上海"]
		fmt.Printf("未找到城市'%s'，使用默认城市'上海'\n", city)
	}

	// 返回模拟天气数据（确保功能可用性）
	// 在实际部署中，可以替换为真实的天气API调用
	fmt.Printf("正在查询%s的天气信息...\n", coords.Name)
	return getMockWeatherData(coords.Name), nil
}

// getMockWeatherData 返回模拟天气数据
//
// 功能说明：
// - 为不同城市提供差异化的模拟天气数据
// - 确保天气查询功能的稳定性和可用性
// - 支持测试和开发环境使用
// - 数据基于城市地理位置特点进行模拟
//
// 参数:
//   - city: 城市名称
//
// 返回:
//   - *SimpleWeatherData: 模拟的天气数据
func getMockWeatherData(city string) *SimpleWeatherData {
	// 根据城市地理位置特点返回不同的模拟数据
	// 南方城市温度较高，北方城市温度较低
	var temp, windSpeed float64
	var description string

	switch city {
	case "上海":
		temp = 25.3
		windSpeed = 12.5
		description = "多云"
	case "北京":
		temp = 22.1
		windSpeed = 8.2
		description = "晴天"
	case "广州":
		temp = 28.5
		windSpeed = 15.3
		description = "小雨"
	case "深圳":
		temp = 29.2
		windSpeed = 10.8
		description = "多云转晴"
	case "杭州":
		temp = 24.7
		windSpeed = 9.1
		description = "阴天"
	case "南京":
		temp = 23.8
		windSpeed = 7.5
		description = "多云"
	case "苏州":
		temp = 25.1
		windSpeed = 11.2
		description = "晴天"
	case "成都":
		temp = 26.4
		windSpeed = 6.8
		description = "阴天"
	case "重庆":
		temp = 27.9
		windSpeed = 13.7
		description = "小雨"
	case "武汉":
		temp = 24.2
		windSpeed = 9.6
		description = "多云"
	default:
		temp = 24.0
		windSpeed = 10.0
		description = "多云"
	}

	return &SimpleWeatherData{
		City:        city,
		Temperature: temp,
		Description: description,
		Humidity:    65,
		WindSpeed:   windSpeed,
	}
}

// getWeatherDescription 根据天气代码获取天气描述
func getWeatherDescription(code int) string {
	weatherMap := map[int]string{
		0:  "晴天",
		1:  "大部分晴天",
		2:  "部分多云",
		3:  "阴天",
		45: "雾",
		48: "霜雾",
		51: "小雨",
		53: "中雨",
		55: "大雨",
		61: "小雨",
		63: "中雨",
		65: "大雨",
		71: "小雪",
		73: "中雪",
		75: "大雪",
		77: "雪粒",
		80: "小雨",
		81: "中雨",
		82: "大雨",
		85: "小雪",
		86: "大雪",
		95: "雷暴",
		96: "雷暴伴冰雹",
		99: "强雷暴伴冰雹",
	}

	if desc, exists := weatherMap[code]; exists {
		return desc
	}
	return "未知天气"
}

// GenerateSimpleWeatherAdvice 生成简单的天气建议
func GenerateSimpleWeatherAdvice(weather *SimpleWeatherData) string {
	var advice strings.Builder

	// 基本信息
	advice.WriteString(fmt.Sprintf("🌤️ **%s今日天气**\n\n", weather.City))
	advice.WriteString(fmt.Sprintf("🌡️ **温度**: %.1f°C\n", weather.Temperature))
	advice.WriteString(fmt.Sprintf("☁️ **天气**: %s\n", weather.Description))
	advice.WriteString(fmt.Sprintf("💨 **风速**: %.1f km/h\n", weather.WindSpeed))

	// 根据温度给出建议
	advice.WriteString("\n**💡 生活建议:**\n")

	if weather.Temperature < 0 {
		advice.WriteString("❄️ 天气严寒，请注意保暖，建议穿厚外套、戴手套和帽子\n")
	} else if weather.Temperature < 10 {
		advice.WriteString("🧥 天气较冷，建议穿保暖衣物，注意防寒\n")
	} else if weather.Temperature < 20 {
		advice.WriteString("👔 天气凉爽，建议穿长袖或薄外套\n")
	} else if weather.Temperature < 30 {
		advice.WriteString("👕 天气温暖，适合穿短袖或薄长袖\n")
	} else {
		advice.WriteString("🌞 天气炎热，建议穿轻薄衣物，注意防暑降温\n")
	}

	// 根据风速给出建议
	if weather.WindSpeed > 30 {
		advice.WriteString("💨 风力很大，外出注意安全，避免在广告牌下停留\n")
	} else if weather.WindSpeed > 15 {
		advice.WriteString("🌬️ 有风，外出时注意防风\n")
	}

	// 根据天气描述给出建议
	weatherDesc := strings.ToLower(weather.Description)
	if strings.Contains(weatherDesc, "雨") {
		advice.WriteString("☔ 有降雨，外出请携带雨具\n")
	} else if strings.Contains(weatherDesc, "雪") {
		advice.WriteString("❄️ 有降雪，路面可能湿滑，外出请注意安全\n")
	} else if strings.Contains(weatherDesc, "晴") {
		advice.WriteString("☀️ 天气晴朗，适合户外活动\n")
	} else if strings.Contains(weatherDesc, "云") {
		advice.WriteString("☁️ 多云天气，适合各种活动\n")
	}

	return advice.String()
}

// IsWeatherQuery 判断用户输入是否为天气查询
//
// 功能特性：
// - 智能关键词识别：支持中英文天气相关词汇
// - 城市名称提取：自动从用户消息中提取城市名称
// - 多轮对话集成：与AI对话系统无缝配合
// - 容错处理：未识别到城市时使用默认城市
//
// 参数:
//   - message: 用户输入的消息内容
//
// 返回:
//   - bool: 是否为天气查询请求
//   - string: 提取的城市名称，如果不是天气查询则返回空字符串
func IsWeatherQuery(message string) (bool, string) {
	// 转换为小写，提高匹配准确性
	message = strings.ToLower(message)

	// 天气相关关键词列表
	// 支持中英文关键词，覆盖常见的天气查询表达方式
	weatherKeywords := []string{
		"天气", "weather", "温度", "气温", "下雨", "晴天", "阴天", "多云",
		"下雪", "刮风", "湿度", "气压", "能见度", "紫外线", "体感温度",
		"降雨", "降雪", "风力", "风向", "空气质量", "pm2.5",
	}

	// 检查是否包含天气关键词
	isWeatherQuery := false
	for _, keyword := range weatherKeywords {
		if strings.Contains(message, keyword) {
			isWeatherQuery = true
			break
		}
	}

	// 如果不是天气查询，直接返回
	if !isWeatherQuery {
		return false, ""
	}

	// 提取城市名称：从用户消息中智能识别城市
	city := extractCityFromMessage(message)
	return true, city
}

// isMapWeatherQuery 判断用户输入是否为地图天气查询
//
// 功能特性：
// - 智能识别地图相关关键词
// - 支持多种地图天气查询表达方式
// - 与基础天气查询功能配合使用
//
// 参数:
//   - message: 用户输入的消息内容
//
// 返回:
//   - bool: 是否为地图天气查询请求
func isMapWeatherQuery(message string) bool {
	// 转换为小写，提高匹配准确性
	message = strings.ToLower(message)

	// 地图天气相关关键词列表
	// 支持多种地图天气查询表达方式
	mapWeatherKeywords := []string{
		"地图", "map", "图层", "layer", "热力图", "heatmap", "实时", "realtime",
		"降雨图层", "rain layer", "交通", "traffic", "拥堵", "congestion",
		"路况", "road condition", "导航", "navigation", "路线", "route",
		"可视化", "visualization", "显示", "display", "查看", "view",
		"降雨分布", "rain distribution", "交通状况", "traffic status",
		"实时地图", "realtime map", "天气地图", "weather map",
	}

	// 检查是否包含地图天气关键词
	for _, keyword := range mapWeatherKeywords {
		if strings.Contains(message, keyword) {
			return true
		}
	}

	return false
}

// extractCityFromMessage 从消息中提取城市名称
//
// 功能说明：
// - 智能城市识别：从用户消息中提取城市名称
// - 模糊匹配：支持部分城市名称匹配
// - 容错处理：未找到城市时返回默认城市
//
// 参数:
//   - message: 用户输入的消息内容
//
// 返回:
//   - string: 提取的城市名称，未找到时返回默认城市"上海"
func extractCityFromMessage(message string) string {
	// 转换为小写，提高匹配准确性
	message = strings.ToLower(message)

	// 遍历城市坐标表，查找匹配的城市名称
	for city := range cityCoordinates {
		if strings.Contains(message, strings.ToLower(city)) {
			return city
		}
	}

	// 容错处理：如果没有找到具体城市，返回默认城市
	// 这确保了天气查询功能的稳定性
	return "上海" // 默认查询上海天气
}

// HandleWeatherQuery 处理天气查询请求
//
// 功能特性：
// - 智能天气查询：自动识别并处理天气查询请求
// - 多轮对话集成：与AI对话系统无缝配合，保存查询记录
// - 友好回复：生成结构化的天气信息和建议
// - 错误处理：完善的错误处理机制，提供用户友好的错误信息
// - 数据持久化：所有天气查询记录自动保存到数据库
//
// 参数:
//   - ctx: 上下文，用于数据库操作超时控制
//   - userMessage: 用户原始消息
//   - city: 查询的城市名称
//   - sessionId: 会话ID，用于多轮对话上下文
//   - userID: 用户ID，用于记录关联
//
// 返回:
//   - string: 格式化的天气信息回复
//   - string: 会话ID，用于多轮对话
//   - error: 错误信息
func HandleWeatherQuery(ctx context.Context, userMessage, city, sessionId string, userID int32) (string, string, error) {
	// 获取天气信息：调用天气查询服务
	weatherData, err := GetSimpleWeatherInfo(ctx, city)
	if err != nil {
		// 错误处理：生成用户友好的错误信息
		errorMsg := fmt.Sprintf("抱歉，无法获取%s的天气信息：%s\n\n您可以尝试：\n1. 检查城市名称是否正确\n2. 稍后再试\n3. 询问其他问题", city, err.Error())

		// 保存错误信息到数据库：确保错误记录也被保存
		record := &models.AiMessage{
			UserId:      userID,
			SessionId:   sessionId,
			UserMessage: userMessage,
			AiMessage:   errorMsg,
			CreatedAt:   time.Now(),
		}
		config.DB.WithContext(ctx).Create(record)

		return errorMsg, sessionId, nil
	}

	// 生成天气建议：将天气数据转换为用户友好的格式
	weatherAdvice := GenerateSimpleWeatherAdvice(weatherData)

	// 构建完整回复：添加友好的回复前缀和后续建议
	response := fmt.Sprintf("根据您的问题，我为您查询了%s的天气信息：\n\n%s\n\n如果您想查询其他城市的天气，请直接告诉我城市名称！", city, weatherAdvice)

	// 保存天气查询结果到数据库：确保查询记录被保存
	record := &models.AiMessage{
		UserId:      userID,
		SessionId:   sessionId,
		UserMessage: userMessage,
		AiMessage:   response,
		CreatedAt:   time.Now(),
	}
	if err = config.DB.WithContext(ctx).Create(record).Error; err != nil {
		return "", "", fmt.Errorf("保存天气查询记录失败: %v", err)
	}

	return response, sessionId, nil
}
